﻿#include <QMessageBox>
#include "SerialPort.h"
#include "public.h"
#include "easylogging++.h"
#include "mainwindow.h"
#include "AreaIdentify.h"

SerialPort::SerialPort(MainWindow& mw) : mainWindow(mw) {
	this->serialPort = new QSerialPort;
	this->sendMsgTimer = new QTimer();
	connect(this->sendMsgTimer, SIGNAL(timeout()), this, SLOT(sendMsgCycle()));
	connect(this->serialPort, SIGNAL(readyRead()), this, SLOT(recvMsg()));

	this->waitConfirmTimer = new QTimer();
	connect(this->waitConfirmTimer, SIGNAL(timeout()), this, SLOT(checkWaitConfirmMsg()));
}

bool SerialPort::init(const QString& portName) {
	this->serialPort->setPortName(portName);
	if (!this->serialPort->open(QIODevice::ReadWrite)) {
		QMessageBox::warning(NULL, "Tip", QStringLiteral("串口打开失败"));
		return false;
	}
	this->serialPort->setBaudRate(9600);
	this->serialPort->setDataBits(QSerialPort::Data8);
	this->serialPort->setStopBits(QSerialPort::OneStop);
	this->serialPort->setParity(QSerialPort::EvenParity);

	this->sendMsgTimer->start(20);
	return true;
}

void SerialPort::close() {
	this->serialPort->close();
}

std::vector<QString> SerialPort::findFreePorts() {
	std::vector<QString> allPorts;

	QList<QSerialPortInfo> ports = QSerialPortInfo::availablePorts();
	for (int i = 0; i < ports.size(); ++i) {
		if (ports.at(i).isNull()) {
			ports.removeAt(i);
			continue;
		}
		allPorts.push_back(ports.at(i).portName());
	}
	if (!ports.size()) {
		QMessageBox::warning(NULL, "Tip", QStringLiteral("找不到空闲串口"));
		return {};
	}
	return allPorts;
}

void SerialPort::sendMsg(const QByteArray& msg) {
	LOG(INFO) << "sendMsg:" << convertToString(msg).toStdString();
	waitSendMsgs.push_back(msg);
}

void SerialPort::startWaitConfirmTimer(uint32_t ms) {
	// this->waitConfirmTimer->start(ms);
}

bool SerialPort::cacheWaitConfirmMsg(uint32_t cmd, const QByteArray& msg) {
	//if (waitConfirmMsgs.find(cmd) != waitConfirmMsgs.end()) {
	//	LOG(ERROR) << "Message has not been confirmed, cmd:" << convertToString(cmd).toStdString() << ", msg:" << convertToString(msg).toStdString();
	//	return false;
	//}
	//waitConfirmMsgs[cmd] = waitConfirmMsg{ std::time(nullptr), msg };
	return true;
}

void SerialPort::confirmWaitConfirmMsg(uint32_t cmd) {
	waitConfirmMsgs.erase(cmd);
}

void SerialPort::handleMsg(const QByteArray& msg) {
	uint32_t DI = uint8_t(msg[9]) << 24 | uint8_t(msg[8]) << 16 | uint8_t(msg[7]) << 8 | uint8_t(msg[6]);
	LOG(INFO) << convertToString(DI).toStdString();

	LOG(INFO) << "msg:" << convertToString(msg).toStdString();

	if (DI == startAreaIdentifyRsp) {
		// 启动台区识别回报
		// mainWindow.getAreaIdentify()->handleStartAreaIdentifyRsp(msg);
	}
	else if (DI == queryTableFileAreaResultRsp) {
		// 查询表档案的台区识别结果
		mainWindow.getAreaIdentify()->handleTableFileAreaResult(msg);
	}
	else if (DI == queryRedundantAreaResultRsp) {
		// 查询多余节点的台区识别结果
		mainWindow.getAreaIdentify()->handleRedundantAreaResult(msg);
	}
	else if (DI == queryTerminalNoRsp) {
		// 查询终端编号回报
		mainWindow.getAreaIdentify()->handleQueryTermialNoResult(msg);
	}
	else if (DI == queryNodeNumberRsp) {
		// 查询从节点数量回报
		mainWindow.getPhaseIdentify()->handleQueryNodeNumberResult(msg);
	}
	else if (DI == batchQueryNodePhaseInfoRsp) {
		// 批量查询从节点相位信息回报
		mainWindow.getPhaseIdentify()->handleBatchQueryNodePhaseInfoResult(msg);
	}
	else if (DI == queryNodeInfoRsp) {
		// 批量查询从节点相位信息回报
		mainWindow.getSearchTable()->handleQueryNodeInfoResult(msg);
	}
}

void SerialPort::sendMsgCycle() {
	if (waitSendMsgs.size() > 0) {
		LOG(INFO) << "sendMsg:" << convertToString(waitSendMsgs.front()).toStdString();
		this->serialPort->write(waitSendMsgs.front());
		waitSendMsgs.pop_front();
	}
}

//接受来自串口的信息
void SerialPort::recvMsg() {
	QByteArray msg = this->serialPort->readAll();
	LOG(INFO) << convertToString(msg).toStdString();
	//do something
	if (recvMsgBuffer.isEmpty() && msg.size() >= 1 && msg[0] == 0x68) {
		recvMsgBuffer.append(msg);
	}
	else if (!recvMsgBuffer.isEmpty()) {
		recvMsgBuffer.append(msg);
	}
	LOG(INFO) << "recvMsg:" << convertToString(recvMsgBuffer).toStdString();
	uint64_t length = 0;
	if (recvMsgBuffer.size() >= 3) {
		if (recvMsgBuffer[0] != 0x68) {
			recvMsgBuffer.clear();
			return;
		}
		length = uint8_t(recvMsgBuffer[2]) << 8 | uint8_t(recvMsgBuffer[1]);
	}
	if (length != 0 && length <= recvMsgBuffer.size()) {
		auto content = recvMsgBuffer.sliced(0, length);
		LOG(INFO) << "content:" << convertToString(content).toStdString();
		recvMsgBuffer.remove(0, length);
		// 处理消息
		handleMsg(content);
		return;
	}
	return;
}

// 一秒检查一次未确认的消息，长时间未确认的，按需求重发
void SerialPort::checkWaitConfirmMsg() {
	for (auto it = waitConfirmMsgs.begin(); it != waitConfirmMsgs.end(); ++it) {
		if (std::time(nullptr) - it->second.timePoint > 30) {
			it->second.timePoint = std::time(nullptr);
			sendMsg(it->second.sendMsg);
		}
	}
}
